package projects

import (
	"encoding/json"
	"fmt"
	"github.com/beego/beego/v2/core/validation"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/beego/beego/v2/server/web/pagination"
	"github.com/kingzcheung/carbon"
	"log"
	"strconv"
	"strings"
	"xpms/app/auth/groups"
	"xpms/controllers"
	"xpms/cores"
	"xpms/cores/utils"
)

// 项目管理
type ManageProjectController struct {
	controllers.BaseController
}

// @Title 分页查询项目数据
// @Description 分页查询项目数据
// @Param	p		query 	int	true		"第几页"
// @Param	status		query 	string			"状态"
// @Param	pageoffset		query 	int			"每页数"
// @Param	keywords		query 	string			"关键字搜索"
// @Success 200 {object} projects.ProjectsAll   int   int  int
// @Failure 403 user not exist
// @router /page [get]
func (u *ManageProjectController) Page() {
	page, err := u.GetInt("p")
	status := u.GetString("status")
	keywords := u.GetString("keywords")
	if err != nil {
		page = 1
	}
	offset, err := u.GetInt("pageoffset")
	if err != nil {
		offset = 15
	}
	// 根据当前用户查询组，如果组中有管理员，这显示全部
	gcondArr := make(map[string]interface{})
	condArr := make(map[string]interface{})
	userid := u.BaseController.UserUserId
	gcondArr["userid"] = userid
	groupid := groups.ListGroupsByUser(gcondArr)
	pgroupid, _ := beego.AppConfig.Int64("groupid")
	isAdmin := false
	for _, value := range groupid {
		if value.Groupid == pgroupid {
			isAdmin = true
			break
		}
	}
	// 如果不是管理员，就当前用户 查询
	if !isAdmin {
		condArr["userid"] = u.BaseController.UserUserId
	}
	condArr["status"] = status
	condArr["keywords"] = keywords

	countUser := ProjectPageCountExec(condArr, page, offset)
	paginator := pagination.SetPaginator(u.Ctx, offset, countUser)
	modeData := ProjectPageExec(condArr, page, offset)
	type data struct {
		Projects []ProjectsAll
		Total    int64
		PageNums int
		Page     int
	}
	d := &data{modeData, paginator.Nums(), paginator.PageNums(), paginator.Page()}
	var responseEntity cores.ResponseEntity
	u.Data["json"] = responseEntity.Build(d).Data
	u.Ctx.Output.Status = responseEntity.StatusCode
	u.ServeJSON()
}

type ProjectDTO struct {
	Name       string
	Aliasname  string
	Started    int64 `json:"Started,string"`
	Ended      int64 `json:"Ended,string"`
	Desc       string
	Status     int
	Projuserid int64 `json:"Projuserid,string"`
	Produserid int64 `json:"Produserid,string"`
	Testuserid int64 `json:"Testuserid,string"`
	Publuserid int64 `json:"Publuserid,string"`
}

// 如果你的 struct 实现了接口 validation.ValidFormer
// 当 StructTag 中的测试都成功时，将会执行 Valid 函数进行自定义验证
func (u *ProjectDTO) Valid(v *validation.Validation) {
	v.Required(u.Name, "name").Message("项目名称不能为空")
	v.Required(u.Aliasname, "aliasname").Message("代号不能为空")
	isStart := utils.IsEmpty(u.Started)
	isEned := utils.IsEmpty(u.Ended)
	//从时间戳中解析
	Started := carbon.CreateFromTimestamp(u.Started)
	if !isStart && Started.Year < 1971 {
		v.AddError("started", "开始日期内容异常") //将错误信息直接返回 配合前文我写的错误信息拼接字段名，就可以做到直接返回完整的错误提示
	}
	//从时间戳中解析
	Ended := carbon.CreateFromTimestamp(u.Ended)
	if !isEned && Ended.Year < 1971 {
		v.AddError("ended", "结束日期内容异常") //将错误信息直接返回 配合前文我写的错误信息拼接字段名，就可以做到直接返回完整的错误提示
	}
	if !isEned && !isStart && u.Started >= u.Ended {
		v.AddError("startEnded", "开始日期大于结束时间")
	}
}

// @Title Create project
// @Description create project
// @Param	body		body 	projects.ProjectDTO	true		"body for project content"
// @Success 200 {string} projects.Projects.Id
// @Failure 403 body is empty
// @router / [post]
func (u *ManageProjectController) Create() {
	var f ProjectDTO
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &f)
	// 开始校验输入值
	valid := validation.Validation{}
	b, err := valid.Valid(&f)
	if err != nil {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
		u.ServeJSON()
		return
	}
	if !b {
		var validMsg []string
		// validation does not pass
		for _, err := range valid.Errors {
			validMsg = append(validMsg, err.Message)
			log.Println(err.Key, err.Message)
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	exists, err1 := GetProjectByAliasname(f.Name)
	if err1 != nil || !utils.IsEmpty(exists.Id) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "代号重复"}
		u.ServeJSON()
		return
	}
	userid := u.BaseController.UserUserId
	//雪花算法ID生成
	id := utils.SnowFlakeId()
	var pro Projects
	pro.Id = id
	pro.Userid = userid
	pro.Name = f.Name
	pro.Aliasname = f.Aliasname
	pro.Started = f.Started
	pro.Ended = f.Ended
	pro.Desc = f.Desc
	err = AddProject(pro)
	var team ProjectsTeam
	teamid := utils.SnowFlakeId()
	team.Id = teamid
	team.Projectid = id
	team.Userid = userid
	AddTeam(team)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息添加成功", "id": fmt.Sprintf("%d", id)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息添加失败"}
	}
	u.ServeJSON()
}

// @Title Update project
// @Description  Update project
// @Param	id		path 	string	true		"project id"
// @Param	body		body 	projects.ProjectDTO	true		"body for project content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id [put]
func (u *ManageProjectController) Update() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的项目为空"}
		u.ServeJSON()
		return
	}
	var f ProjectDTO
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &f)
	// 开始校验输入值
	valid := validation.Validation{}
	b, err := valid.Valid(&f)
	if err != nil {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
		u.ServeJSON()
		return
	}
	if !b {
		var validMsg []string
		// validation does not pass
		for _, err := range valid.Errors {
			validMsg = append(validMsg, err.Message)
			log.Println(err.Key, err.Message)
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	userss, err1 := GetProject(ids)
	if err1 != nil || utils.IsEmpty(userss.Aliasname) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "项目不存在"}
		u.ServeJSON()
		return
	}
	exists, err1 := GetProjectByAliasname(f.Name)
	if err1 != nil || (!utils.IsEmpty(exists.Id) && userss.Id != exists.Id) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "项目代号重复"}
		u.ServeJSON()
		return
	}
	var pro Projects
	pro.Name = f.Name
	pro.Aliasname = f.Aliasname
	pro.Started = f.Started
	pro.Ended = f.Ended
	pro.Desc = f.Desc
	pro.Projuserid = f.Produserid
	pro.Produserid = f.Projuserid
	pro.Testuserid = f.Testuserid
	pro.Publuserid = f.Publuserid
	err = UpdateProject(ids, pro)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败" + err.Error()}
	}
	u.ServeJSON()
}

// @Title Get
// @Description get Projects  by id
// @Param	id		path 	string	true		"The key for Projects"
// @Success 200 {object} projects.Projects
// @Failure 403 :id is empty
// @router /:id [get]
func (u *ManageProjectController) Get() {
	uid := u.GetString(":id")
	if uid != "" {
		var responseEntity cores.ResponseEntity
		int64, err := strconv.ParseInt(uid, 10, 64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
			return
		}
		modeData, err := GetProject(int64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
		} else {
			u.Data["json"] = responseEntity.Build(modeData).Data
			u.Ctx.Output.Status = responseEntity.StatusCode
		}
	}
	u.ServeJSON()
}

// @Title Update Projects status
// @Description  Update Projects status
// @Param	id		path 	string	true		"Projects id"
// @Param	status	query 	string	true		"状态"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/status [put]
func (u *ManageProjectController) UpdateStatus() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的用户为空"}
		u.ServeJSON()
		return
	}
	status, err := u.GetInt("status")
	if err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "状态为空"}
		u.ServeJSON()
		return
	}
	exist, err1 := GetProject(ids)
	if err1 != nil || utils.IsEmpty(exist.Aliasname) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "用户不存在"}
		u.ServeJSON()
		return
	}
	err = ChangeProjectStatus(ids, status)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败" + err.Error()}
	}
	u.ServeJSON()
}
